
const vscode = require('vscode');
const { user32, traverseMenu, executeMenuCommand } = require('../functions/window_api');
const { Servers, Application } = require('./ServerProcess');
const { sleep_ms } = require('../functions/helper');
const { saveReloadRules } = require('../onSaveReloadRules');

const commands = {
    heavyLoad: "extension.mir-config.heavyLoad",
    console: 'extension.mir-config.consolelog',
    picker: 'extension.mir-config.quickMenuPicker'
}


class QuickPickMenu {
    /**
     * 
     * @param {Application} app 
     * @param {MirServerMenuTreeViewProvider} menuProvider 
     */
    constructor(app, menuProvider) {
        this.menus = menuProvider.getMenuItems();
        this.quickPick = vscode.window.createQuickPick();
        this.quickPick.placeholder = "输入数字或关键词筛选指令";
        this.quickPick.items = this.filterMenus([], this.menus)
        this.quickPick.show();

        // 动态更新选项列表
        this.quickPick.onDidChangeValue(value => {
            const valueArr = value.toLowerCase().split('');
            this.quickPick.items = this.filterMenus(valueArr, menulist)
        });

        // 处理选择确认
        this.quickPick.onDidAccept(() => {
            const selection = this.quickPick.selectedItems[0];
            if (selection) {
                executeMenuCommand(app.mainHandle.hwnd, [selection.source])
            }
            this.quickPick.hide();
        });
    }

    /**
        * @param {ReturnType<traverseMenu>} list 
        * @returns {vscode.QuickPickItem[]}
        */
    filterMenus(valueArr, list, parentTitle = []) {
        /** @type {vscode.QuickPickItem[]} */
        const result = []
        for (let index = 0; index < list.length; index++) {
            const parent = JSON.parse(JSON.stringify(parentTitle))
            if (index === 0) {
                result.push({
                    label: parent.join(" - "),
                    kind: vscode.QuickPickItemKind.Separator
                })
            }
            const item = list[index];
            if (item.children && item.children.length > 0) {
                parent.push(item.text)
                result.push(...this.filterMenus(valueArr, item.children, parent))
                continue
            }
            if (!item.text) {
                continue
            }
            const textArr = item.text.toLowerCase().split('');
            const is = valueArr.every(v => {
                const index = textArr.indexOf(v)
                if (index !== -1) {
                    textArr.splice(index, 1)
                    return true
                }
                return false
            })
            if (is || item.id == parseInt(value)) {
                result.push({
                    label: item.text,
                    description: `#${item.id}`,
                    alwaysShow: true,
                    source: item,
                })
            }
        }
        return result
    }
}

class MirServerMenuTreeItem extends vscode.TreeItem {
    /**
     * 
     * @param {MenuInfo} menu 
     */
    constructor(menu) {
        super(menu.text, menu.children?.length > 0 ? vscode.TreeItemCollapsibleState.Collapsed : vscode.TreeItemCollapsibleState.None);
        this.id = menu.id
        this.command = { arguments: [menu], command: commands.heavyLoad }
    }
}




/**
 * @implements {vscode.TreeDataProvider<MirServerMenuTreeItem>}
 */

class MirServerMenuTreeViewProvider {
    /**
     * @param {vscode.ExtensionContext} context 
     */
    constructor(context) {
        this.context = context;
    }

    /**
     * 
     * @param {vscode.TextDocument} document 
     * @returns 
     */
    onDidSaveTextDocument(document) {
        if (!this.handle) {
            console.log("M2Server未启动");
            return
        }
        const reloadMenus = this.filterReloadMenus(this.getMenuItems())
        const rules = saveReloadRules.filter(rule => rule.rules.some(reg => reg(document.fileName)))
        const menus = rules.map(rule => reloadMenus.find(menu => rule.text.every(reg => reg.test(menu.text))))
        if (menus) {
            executeMenuCommand(this.handle, menus)
        }
    }


    /**
     * 
     * @param {Application} app 
     */
    refresh(app) {
        this.app = app
        this.handle = app.mainHandle.hwnd
        if (!this.initialized) {
            this.initialized = true
            this.outputChannel = vscode.window.createOutputChannel('M2日志');
            this.consoleBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left);
            this.consoleBar.text = 'M2日志'
            this.consoleBar.command = commands.console
            this.context.subscriptions.push(
                vscode.window.registerTreeDataProvider("mir_script_activity_m2menu", this),
                vscode.workspace.onDidSaveTextDocument((...args) => this.onDidSaveTextDocument.apply(this, args)),
                vscode.commands.registerCommand(commands.console, this.outputChannel.show),
                vscode.commands.registerCommand(commands.heavyLoad, (menu) => executeMenuCommand(app.mainHandle.hwnd, [menu])),
                vscode.commands.registerCommand(commands.picker, () => new QuickPickMenu(app, this)),
            )
        }
        this.consoleBar.show()
        app.on("message", (...args) => this.onMessage.apply(this, args))
        app.subscribe()
    }
    /**
     * 
     * @param {*} logs 
     */
    async onMessage(logs) {
        this.outputChannel.clear();
        this.outputChannel.appendLine(logs.message);
        const updateLines = logs.lines.slice(-2)
        for (let index = 0; index < updateLines.length; index++) {
            const line = updateLines[index];
            this.consoleBar.text = line.length > 30 ? line.substring(0, 30) + "..." : line;
            await sleep_ms(100)
        }
    }
    dispose() {
        this.outputChannel.hide();
        this.consoleBar.hide();
        this.app.off("message", this.onMessage)
    }

    /**
     * @param {vscode.ExtensionContext} context
     * @param {Servers} servers 
     */
    static init(context, servers) {
        const m2menuViewProvider = new MirServerMenuTreeViewProvider(context)
        const mirServer = servers.servers.find(v => v.app.name == "M2Server")
        if (mirServer?.app?.mainHandle?.hwnd) {
            m2menuViewProvider.refresh(mirServer.app)
        }
        servers.on("changeStatus", (app) => {
            if (app.name != "M2Server") {
                return
            }
            if (app.status == Application.STATUS_LAUNCHED && app.mainHandle) {
                m2menuViewProvider.refresh(app)
            } else if (app.status == Application.STATUS_STOPING) {
                m2menuViewProvider.dispose()
            }
        })
    }


    getChildren(element) {
        if (element) {
            return element.children.filter(v => !!v.text)
        }
        const list = this.getMenuItems()
        if (!list) {
            return [new vscode.TreeItem("菜单加载失败！")]
        }
        return list.filter(v => !!v.text)
    }

    getTreeItem(element) {
        return new MirServerMenuTreeItem(element);
    }

    getMenuItems() {
        if (!this.menus) {
            const menu = user32.GetMenu(this.handle);
            if (!menu) return null
            this.menus = traverseMenu(menu)
        }
        return this.menus
    }

    /**
     * 
     * @param {MenuInfo[]} list 
     * @returns {MenuInfo[]}
     */
    filterReloadMenus(list) {
        for (const item of list) {
            if (item.text.startsWith("重新加载")) {
                return item.children
            }
            if (item.children) {
                return this.filterReloadMenus(item.children)
            }
        }
    }
}

module.exports = { MirServerMenuTreeViewProvider };